﻿#region File Header
//-----------------------------------------------------------------------------
// SibLib
//
// Copyright (C) 2010 Julien Villers
// This program is distributed under the terms of the 
// GNU Lesser General Public License (LGPL).
// See Docs/lgpl.txt and Docs/gpl.txt
//
// This file is based on a sample by Nick Gravelyn:
//  http://blog.nickgravelyn.com/2009/07/a-more-robust-exception-system/
//-----------------------------------------------------------------------------
#endregion

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace SibLib.GameComponents
{
    public class ExceptionGame : Game
    {
        private const string errorTitle = "Unexpected Error";
        private const string errorMessage =
           "The game had an unexpected error and had to shut down. " +
           "We're sorry for the inconvenience.";

        private static readonly string[] errorButtons = new[] 
        { 
            "Exit to Dashboard", 
            "View Error Details" 
        };

        private readonly Exception exception;
        private bool shownMessage;
        private bool displayException;
        private readonly GamerServicesComponent m_GamerServiceComponent;

        private SpriteBatch batch;
        private SpriteFont font;

        public ExceptionGame(Exception e, Game g)
        {
            new GraphicsDeviceManager(this)
            {
                PreferredBackBufferWidth = 1280,
                PreferredBackBufferHeight = 720
            };
            exception = e;
            Content.RootDirectory = "Content";
            if (g is GameWithGSC)
                m_GamerServiceComponent = ((GameWithGSC)g).GSC;
            else
                m_GamerServiceComponent = null;
        }

        protected override void Initialize()
        {
#if XBOX360
            // No component in source game?
            if (m_GamerServiceComponent == null)
                Components.Add(new GamerServicesComponent(this));
#endif

            base.Initialize();

            // Found a component in source game?
            if (m_GamerServiceComponent != null)
                Components.Add(m_GamerServiceComponent);
        }

        protected override void LoadContent()
        {
            batch = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>("SpriteFontDebug");
            font.DefaultCharacter = '?';

#if XBOX360
            shownMessage = false;
            displayException = false;
#elif WINDOWS
            shownMessage = true;
            displayException = true;
#endif
        }

        protected override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            if (shownMessage)
            {
                for (int i = 0; i != 4; i++)
                {
                    GamePadState state = GamePad.GetState((PlayerIndex)i);
                    if (state.Buttons.A == ButtonState.Pressed ||
                        state.Buttons.Start == ButtonState.Pressed ||
                        state.Buttons.B == ButtonState.Pressed ||
                        state.Buttons.Back == ButtonState.Pressed)
                    {
                        Exit();
                    }
                }
                return;
            }

#if XBOX360
            try
            {
                if (!Guide.IsVisible)
                {
                    Guide.BeginShowMessageBox(
                       PlayerIndex.One,
                       errorTitle,
                       errorMessage,
                       errorButtons,
                       0,
                       MessageBoxIcon.Error,
                       result =>
                       {
                           int? choice = Guide.EndShowMessageBox(result);

                           if (choice.HasValue && choice.Value == 1)
                               displayException = true;
                           else
                               Exit();
                       },
                       null);
                    shownMessage = true;
                }
            }
            catch { } 
#endif
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            if (displayException)
            {
                Vector2 p = new Vector2(
                   GraphicsDevice.Viewport.TitleSafeArea.X,
                   GraphicsDevice.Viewport.TitleSafeArea.Y);
                batch.Begin();
                string toString = exception.ToString();
                batch.DrawString(font, toString, p, Color.White);
                batch.End();
            }

            base.Draw(gameTime);
        }
    }
}
